package com.yiji.fintech.musfinance.common.dispatcher;

import com.google.common.collect.Maps;
import com.google.common.eventbus.EventBus;
import com.yiji.fintech.musfinance.center.base.order.OrderFacade;
import com.yiji.fintech.musfinance.center.base.result.ResultFacade;
import com.yiji.fintech.musfinance.common.context.SpringApplicationContext;
import com.yiji.fintech.musfinance.common.converter.Order2Domain2EventConverter;
import com.yiji.fintech.musfinance.common.dispatcher.base.BaseDispatcher;
import com.yiji.fintech.musfinance.common.eventbus.event.base.BaseEvent;
import com.yiji.fintech.musfinance.common.eventbus.listener.base.ListenerBase;
import com.yiji.fintech.musfinance.common.exception.ReflectEntityException;
import com.yiji.fintech.musfinance.common.factory.listenner.ListennerLoadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 事件分发器
 * Created by ouwen@yiji.com} on 2017/9/13.
 */
@Slf4j
@Component
public class Dispatcher extends BaseDispatcher {
    @Autowired
    private Order2Domain2EventConverter order2Domain2Event;
    @Autowired
    private ListennerLoadFactory loadFactory;

    @Override
    public void dispatch(OrderFacade order, ResultFacade result) {
        EventBus eventBus = new EventBus();
        checkOrder(order);//order->check
        register(eventBus);//注册事件监听器
        BaseEvent eventBase = order2Domain2Event.doConverter(order);//order转换为event并设置domain
        eventBase.setResult(result);
        eventBus.post(eventBase);//消息总线投递事件
    }

    /**
     * 注册所有监听器到当前消息总线
     * @param eventBus
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private Map<String,ListenerBase> register(EventBus eventBus){
        Map<String,Class> listenerClass = loadFactory.getListennerMap();
        Set<Map.Entry<String,Class>> entrySet = listenerClass.entrySet();
        Iterator<Map.Entry<String,Class>> iterator = entrySet.iterator();
        Map<String,ListenerBase> allListenerMap = Maps.newHashMap();
        while (iterator.hasNext()){
            Map.Entry<String,Class> entry = iterator.next();
            Class aClass = entry.getValue();
            ListenerBase listenerBase;
            try {
                listenerBase = (ListenerBase)SpringApplicationContext.getBeanByClass(aClass);
            } catch (Exception e) {
                throw new ReflectEntityException(e.getMessage());
            }
            eventBus.register(listenerBase);
            allListenerMap.put(entry.getKey(),listenerBase);
        }
        return allListenerMap;
    }
}
